﻿#include "CUartRecvModule.h"
#include "MsgID.h"
#include "MsgStruct.h"

#include <string.h>
#include <stdio.h>
#include <Windows.h>

#pragma warning(disable:4996)

static CBossModule* mBoss = NULL;
static CUartRecvModule uart_recv_mod;
static int isUartRecvEnd = 0;

static char _log_buf[1024] = {0};

#define CLINET_DEBUG_LOG(fmt, ...) { \
	memset(_log_buf, 0, sizeof(_log_buf)); \
	sprintf(_log_buf, "%s:%d fn:%s " fmt "\n", strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__); \
	WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), _log_buf, strlen(_log_buf), NULL, NULL); \
}

static int ON_MODULE_MSG(CUartRecvModule, MSG_ID_START_UART_RECV) {
	//CLINET_DEBUG_LOG(" atoms count=%d", 111);
	HANDLE com_handle = (HANDLE)(((ST_START_UART_RECV*)msg)->ptr);

	char buff[1024] = { 0 };
	char str[2048] = { 0 };
	DWORD res, factbyte;
	COMSTAT rst;
	int fError, commEvError;
	DWORD dwEvtMask, CommResult, readResult;
	BOOL bRet;
	BOOL fWaitingOnStat = FALSE;  // indicate if wait comm event is pending.  
	OVERLAPPED osComm = { 0 }; // overlapped structure for comm event operations  
	OVERLAPPED osReader = { 0 };  // overlapped structure for read operations

	if (NULL == com_handle) {
		return -1;
	}

	osComm.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (osComm.hEvent == NULL) {
		//AfxMessageBox(_T("Create comm Event failed!"));
	}
	osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (osReader.hEvent == NULL) {
		//AfxMessageBox(_T("Create reader Event failed!\n"));
	}
	

	while (!isUartRecvEnd) {
		if (!fWaitingOnStat) {
			bRet = WaitCommEvent(com_handle, &dwEvtMask, &osComm);
			if (!bRet) {
				commEvError = GetLastError();
				//ASSERT(commEvError == ERROR_IO_PENDING);
				fWaitingOnStat = TRUE;
			}
			else {
				//WaitCommEvent always will return FALSE for overlapped I/O  
			}
		}
		/*wait for pending operations to complete*/
		if (fWaitingOnStat) {
			CommResult = WaitForSingleObject(osComm.hEvent, 500); //Now it can't get the event???Block for ever!!  

			switch (CommResult) {
			case WAIT_OBJECT_0:
				ClearCommError(com_handle, &res, &rst);
				if (!ReadFile(com_handle, buff, rst.cbInQue, &factbyte, &osReader)) {
					fError = GetLastError();
					if (ERROR_ACCESS_DENIED == fError) {
						//isUartRecvEnd = 1;
						// need Send Notify to Main Module TODO 
						continue;
					}
					//ASSERT(fError == ERROR_IO_PENDING || ERROR_NOACCESS == fError);
					readResult = WaitForSingleObject(osReader.hEvent, 500);
					switch (readResult) {
					case WAIT_OBJECT_0:
						buff[rst.cbInQue] = 0;
						fWaitingOnStat = FALSE;

						for (DWORD i = 0; i < rst.cbInQue; ++i) {
							ST_UART_RECV_1BYTE msg = {{MSG_ID_UART_RECV_1BYTE, sizeof(ST_UART_RECV_1BYTE)}, buff[i]};
							AS_MODULE(mBoss)->sendMsg(AS_MODULE(mBoss), AS_MSG(&msg));
							//push1char(buff[i], pdlg);
						}
						memset(buff, 0, 1024);
					case WAIT_TIMEOUT:
						//ClearCommError(m_hCommPort,&res,&rst);  
						//SetCommMask(m_hCommPort,EV_RXCHAR|EV_RXFLAG);  
						break;
					default:
						//do nothing!  
						break;
					}
				} else {
					buff[rst.cbInQue] = 0;
					fWaitingOnStat = FALSE;

					for (DWORD i = 0; i < rst.cbInQue; ++i) {
						//push1char(buff[i], pdlg);
					}
					memset(buff, 0, 1024);
				}
				break;
			case WAIT_TIMEOUT:
				//ClearCommError(m_hCommPort,&res,&rst);  
				//SetCommMask(m_hCommPort,EV_RXCHAR|EV_RXFLAG);  
				break;
			default:
				//do nothing!  
				break;
			}
		}
	}
	return 0;
}

static int reg_msgid_func(CModule* thes) {
	REG_MODULE_MSG_FUNC(CUartRecvModule, thes, MSG_ID_START_UART_RECV);
    return 0;
}

int construct_uart_recv_module(CUartRecvModule* thes, const char* module_name) {
	construct_module(&thes->parent, module_name);
	reg_msgid_func(AS_MODULE(thes));
	AS_MODULE(thes)->run(AS_MODULE(thes), USE_DEFAULT_MODULE_ENTRY);
	return 0;
}

int init_uart_recv_module(CBossModule* boss) {
	mBoss = boss;
	construct_uart_recv_module(&uart_recv_mod, "uart recv module");
	return 0;
}

int start_uart_recv(void** uartHandle) {
	ST_START_UART_RECV start = {{MSG_ID_START_UART_RECV, sizeof(void**)}, uartHandle};
	AS_MODULE(&uart_recv_mod)->sendMsg(AS_MODULE(&uart_recv_mod), &start.msg);
	isUartRecvEnd = 0;
	return 0;
}

int stop_uart_recv() {
	isUartRecvEnd = 1;
	return 0;
}

